package com.itheima.auth.service.impl;

import com.itheima.auth.mapper.AdminMapper;
import com.itheima.auth.service.AuthService;
import com.itheima.model.admin.dtos.LoginDto;
import com.itheima.model.admin.pojos.Admin;
import com.itheima.model.admin.vos.AdminInfoVo;
import com.itheima.model.admin.vos.AdminLoginVo;
import com.itheima.model.common.dtos.ResponseResult;
import com.itheima.model.common.enums.AppHttpCodeEnum;
import com.itheima.utils.common.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.itheima.common.redis.CacheService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 认证服务实现类
 * 
 * @author itheima
 */
@Service
@Slf4j
public class AuthServiceImpl implements AuthService {

    @Autowired
    private AdminMapper adminMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private CacheService cacheService;

    /**
     * Token黑名单前缀
     */
    private static final String TOKEN_BLACKLIST_PREFIX = "auth:token:blacklist:";

    @Override
    public ResponseResult login(LoginDto dto) {
        // 1. 参数校验
        if (dto == null || StringUtils.isBlank(dto.getUsername()) || StringUtils.isBlank(dto.getPassword())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "用户名或密码不能为空");
        }

        // 2. 查询管理员
        Admin admin = adminMapper.selectByUsername(dto.getUsername());
        if (admin == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "用户名或密码错误");
        }

        // 3. 验证密码
        if (!passwordEncoder.matches(dto.getPassword(), admin.getPassword())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR, "用户名或密码错误");
        }

        // 4. 检查账号状态
        if (admin.getStatus() == null || admin.getStatus() != 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.ACCOUNT_DISABLED);
        }

        // 5. 查询角色和权限
        List<String> roles = adminMapper.selectRolesByAdminId(admin.getId());
        List<String> permissions = adminMapper.selectPermissionsByAdminId(admin.getId());

        // 6. 生成JWT Token
        String token = JwtUtil.getAdminToken(
                admin.getId(),
                admin.getUsername(),
                admin.getNickname(),
                roles,
                permissions
        );

        // 7. 更新最后登录时间（异步更新，不影响响应）
        admin.setLastLoginTime(new Date());
        // 这里可以记录登录IP，从request中获取
        adminMapper.updateById(admin);

        // 8. 构造返回数据
        AdminInfoVo adminInfo = AdminInfoVo.builder()
                .id(admin.getId())
                .username(admin.getUsername())
                .nickname(admin.getNickname())
                .avatar(admin.getAvatar())
                .email(admin.getEmail())
                .phone(admin.getPhone())
                .roles(roles)
                .permissions(permissions)
                .build();

        AdminLoginVo loginVo = AdminLoginVo.builder()
                .token(token)
                .adminInfo(adminInfo)
                .expiresIn(3600L)  // 1小时
                .build();

        log.info("管理员登录成功：{}", admin.getUsername());
        return ResponseResult.okResult(loginVo);
    }

    @Override
    public ResponseResult logout(String token) {
        if (StringUtils.isBlank(token)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        try {
            // 将token加入黑名单（Redis），设置过期时间为token的剩余有效期
            String key = TOKEN_BLACKLIST_PREFIX + token;
            cacheService.set(key, "1");
            cacheService.expire(key, 1, TimeUnit.HOURS);
            
            log.info("管理员退出登录成功");
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        } catch (Exception e) {
            log.error("退出登录失败", e);
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
    }

    @Override
    public ResponseResult refreshToken(String token) {
        if (StringUtils.isBlank(token)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        // 检查token是否在黑名单中
        String blacklistKey = TOKEN_BLACKLIST_PREFIX + token;
        if (cacheService.exists(blacklistKey)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.TOKEN_INVALID, "Token已失效，请重新登录");
        }

        // 验证token是否有效
        if (!JwtUtil.validateToken(token)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.TOKEN_INVALID);
        }

        // 获取管理员ID
        Integer adminId = JwtUtil.getUserId(token);
        if (adminId == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.TOKEN_INVALID);
        }

        // 查询管理员信息
        Admin admin = adminMapper.selectById(adminId);
        if (admin == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "账号不存在");
        }
        if (admin.getStatus() != 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.ACCOUNT_DISABLED);
        }

        // 查询角色和权限
        List<String> roles = adminMapper.selectRolesByAdminId(admin.getId());
        List<String> permissions = adminMapper.selectPermissionsByAdminId(admin.getId());

        // 生成新token
        String newToken = JwtUtil.getAdminToken(
                admin.getId(),
                admin.getUsername(),
                admin.getNickname(),
                roles,
                permissions
        );

        // 将旧token加入黑名单
        String key = TOKEN_BLACKLIST_PREFIX + token;
        cacheService.set(key, "1");
        cacheService.expire(key, 1, TimeUnit.HOURS);

        log.info("刷新Token成功：{}", admin.getUsername());
        return ResponseResult.okResult(newToken);
    }

    @Override
    public ResponseResult getCurrentAdmin(String token) {
        if (StringUtils.isBlank(token)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        // 检查token是否在黑名单中
        String blacklistKey = TOKEN_BLACKLIST_PREFIX + token;
        if (cacheService.exists(blacklistKey)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.TOKEN_INVALID, "Token已失效，请重新登录");
        }

        // 验证token
        if (!JwtUtil.validateToken(token)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.TOKEN_INVALID);
        }

        // 获取管理员ID
        Integer adminId = JwtUtil.getUserId(token);
        if (adminId == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.TOKEN_INVALID);
        }

        // 查询管理员信息
        Admin admin = adminMapper.selectById(adminId);
        if (admin == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "账号不存在");
        }
        if (admin.getStatus() != 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.ACCOUNT_DISABLED);
        }

        // 查询角色和权限
        List<String> roles = adminMapper.selectRolesByAdminId(admin.getId());
        List<String> permissions = adminMapper.selectPermissionsByAdminId(admin.getId());

        // 构造返回数据
        AdminInfoVo adminInfo = AdminInfoVo.builder()
                .id(admin.getId())
                .username(admin.getUsername())
                .nickname(admin.getNickname())
                .avatar(admin.getAvatar())
                .email(admin.getEmail())
                .phone(admin.getPhone())
                .roles(roles)
                .permissions(permissions)
                .build();

        return ResponseResult.okResult(adminInfo);
    }
}

